#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void printMatriz(int *m, int linhas, int colunas)
{
	int *m_temp = m;
	int i, j;
	for(i = 0; i < linhas; i++)
	{
		printf("|");
		for(j = 0; j < colunas; j++)
		{
			printf(" %d |", *(m_temp));
			m_temp++;
		}
		printf("\n");
	}
}

void zeraMatriz(int *m, int linhas, int colunas){
	int i, j;
	for(i = 0; i < linhas; i++)
	{
		for(j = 0; j < colunas; j++)
		{
			*m = 0;
			m++;
		}
	}
}

int formula(int valor, int a, int b, int c, int d)
{
	int resultado = valor + ( 3 * ( (a + b + c + d) - (4 * valor) ) );
	
	return resultado;
}

int mGet(int *m, int l, int c, int linhas, int colunas)
{
	int *m_temp = m;
	//nao estou usando ....
	return *( m_temp + c + (l * colunas) );
}

void mSet(int *m, int l, int c, int linhas, int colunas, int valor)
{
	int *m_temp = m;
	//nao estou usando ....
	*( m_temp + c + (l * colunas) ) = valor;
}

main(int argc, char *argv[])
{
	int teste = formula(11, 1, 12, 21, 10);
	printf("Teste %d\n", teste);
	//MPI
	int mpierr, rank, size, *index;
	char message[20];
	mpierr = MPI_Init(&argc, &argv);
	if (mpierr < 0)
	{
		printf ("Nao foi possivel inicializar o processo MPI!\n");
		return;
	}
	
	//Pego o rank
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &size);
	
	//auxiliares
	int i, j;
	
	//Calculo
	int valor, a, b, c, d, resultado;
		
	if(rank == 0){
	
		//FILE
		char file_buffer[1024];
		int linhas, colunas, l, c;
		FILE *fp;
		
		//Abro o arquivo
		fp = fopen("dimensoes_e_condicoes.txt", "r");
		
		//Leio as dimensões
		fscanf(fp, "%d;%d", &linhas, &colunas);
		printf("Dimensao com  %d linhas por %d colunas \n", linhas, colunas);
		
		//zero os valores
		//int matriz[linhas][colunas];
		/*
		for(l = 0; l < linhas; l++)
		{
			for(c = 0; c < colunas; c++)
			{
				matriz[l][c] = 0;
			}	
		}
		*/
		int *matriz = (int *) malloc(linhas*colunas*sizeof(int));
		int *m = matriz;
		
		int *matriz_calculada = (int *) malloc(linhas*colunas*sizeof(int));
		int *mc = matriz_calculada;
		
		zeraMatriz(m, linhas, colunas);
		zeraMatriz(mc, linhas, colunas);
		
		m = matriz;
		mc = matriz_calculada;
		
		//preparo para o parse dos valores a serem preenchidos na matrizd
		char delims[] = ";";
		char *result = NULL;
		i = 0; //linha
		while( fscanf(fp, "%s", file_buffer) > 0 )
		{
			j = 0;//coluna
			result = strtok(file_buffer, delims);
			while( result != NULL )
			{
				int valor = atoi(result);
				*m = valor;
				m++;
				result = strtok( NULL, delims );
				j++;
			}
			i++;
		}
		
		fclose(fp);
		
		//imprimo matriz
		m = matriz;
		printMatriz(m, linhas, colunas);
		
		//calculo de teste
		for(i = 1; i < linhas-1; i++)
		{
			for(j = 1; j < colunas-1; j++)
			{
				valor = mGet(m, i, j, linhas, colunas);
				a = mGet(m, i-1, j, linhas, colunas);
				b = mGet(m, i, j+1, linhas, colunas);
				c = mGet(m, i+1, j, linhas, colunas);
				d = mGet(m, i, j-1, linhas, colunas);
				
				resultado = formula(valor, a, b, c, d);
				
				//printf("Para o valor: %d - a: %d, b: %d, c: %d, d: %d = %d\n", valor, a, b, c, d, resultado);

				mSet(mc, i, j, linhas, colunas, resultado);
			}
		}
		printf("Calculada seria:\n");
		mc = matriz_calculada;
		printMatriz(mc, linhas, colunas);
	}
	
	MPI_Bcast(message, 1, MPI_CHAR, 0, MPI_COMM_WORLD);
	printf("A mensagem recebida foi: %s \n\n\n\n", message);
	
	MPI_Finalize();
} 
